package com.test.xq.customdemo.customtools;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by xq on 17/5/2.
 */


//Path之完结篇
public class CustomView5 extends View {

    private Paint mPaint = new Paint();
    private int mWidth,mHeight;

    public CustomView5(Context context) {
        super(context,null);
    }

    public CustomView5(Context context, AttributeSet attrs) {
        super(context, attrs);
        initPaint();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mWidth=w;
        mHeight=h;
    }

    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        computeBounds(canvas);
    }

    private void initPaint() {
        mPaint.setColor(Color.BLACK);           // 画笔颜色 - 黑色
        mPaint.setStyle(Paint.Style.STROKE);    // 填充模式 - 描边
        mPaint.setStrokeWidth(10);              // 边框宽度 - 10
    }

    //此类方法可以看到和前面的一些方法看起来很像，只是在前面多了一个r，那么这个rXxx和前面的一些方法有什么区别呢？
    //rXxx方法的坐标使用的是相对位置(基于当前点的位移)，而之前方法的坐标是绝对位置(基于当前坐标系的坐标)。
    //相对坐标和绝对坐标
    private void rXxx(Canvas canvas){
        Path path = new Path();
        path.moveTo(100,100);
        //path.lineTo(100,200);
        //canvas.drawPath(path,mPaint);

        path.rLineTo(100,200);
        canvas.drawPath(path,mPaint);

    }

    //填充模式
    //PS: 白色为背景色，黑色为填充色。
    private void fillType(Canvas canvas){
        mPaint.setStyle(Paint.Style.FILL);   // 设置画布模式为填充

        canvas.translate(mWidth/2,mHeight/2);   // 移动画布(坐标系)

        Path path = new Path();

        //path.setFillType(Path.FillType.EVEN_ODD);                   // 设置Path填充模式为 奇偶规则
        path.setFillType(Path.FillType.INVERSE_EVEN_ODD);   // 反奇偶规则

        path.addRect(-200,-200,200,200, Path.Direction.CW);      // 给Path中添加一个矩形
        canvas.drawPath(path,mPaint);
    }

    //图形边的方向对非零奇偶环绕数规则填充结果的影响
    private void fillType1(Canvas canvas){
        mPaint.setStyle(Paint.Style.FILL);  // 设置画笔模式为填充

        canvas.translate(mWidth/2,mHeight/2);   // 移动画布(坐系)

        Path path =new Path();   // 创建Path

        // 添加小正方形 (通过这两行代码来控制小正方形边的方向,从而演示不同的效果)
         path.addRect(-200, -200, 200, 200, Path.Direction.CW);
        //path.addRect(-200, -200, 200, 200, Path.Direction.CCW);

        // 添加大正方形
        path.addRect(-400,-400,400,400, Path.Direction.CCW);

        path.setFillType(Path.FillType.WINDING);     // 设置Path填充模式为非零环绕规则

        canvas.drawPath(path,mPaint);    // 绘制Path
    }

    //布尔操作(API19)
    //布尔操作与我们中学所学的集合操作非常像，只要知道集合操作中等交集，并集，差集等操作，那么理解布尔操作也是很容易的。
    //布尔操作是两个Path之间的运算，主要作用是用一些简单的图形通过一些规则合成一些相对比较复杂，或难以直接得到的图形。
    //DIFFERENCE	差集  Path1中减去Path2后剩下的部分
    //REVERSE_DIFFERENCE	差集   Path1中减去Path2后剩下的部分
    //INTERSECT	交集	Path1与Path2相交的部分
    //UNION	并集	包含全部Path1和Path2
    //XOR	异或	包含Path1与Path2但不包括两者相交的部分

    // 对 path1 和 path2 执行布尔运算，运算方式由第二个参数指定，运算结果存入到path1中。
    //path1.op(path2, Path.Op.DIFFERENCE);

    // 对 path1 和 path2 执行布尔运算，运算方式由第三个参数指定，运算结果存入到path3中。
    //path3.op(path1, path2, Path.Op.DIFFERENCE)
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    private void opTest(Canvas canvas){
        canvas.translate(mWidth / 2, mHeight / 2);
        mPaint.setStyle(Paint.Style.FILL);

        Path path1 = new Path();
        Path path2 = new Path();
        Path path3 = new Path();
        Path path4 = new Path();

        path1.addCircle(0, 0, 200, Path.Direction.CW);
        path2.addRect(0, -200, 200, 200, Path.Direction.CW);
        path3.addCircle(0, -100, 100, Path.Direction.CW);
        path4.addCircle(0, 100, 100, Path.Direction.CCW);


        path1.op(path2, Path.Op.DIFFERENCE);
        path1.op(path3, Path.Op.UNION);
        path1.op(path4, Path.Op.DIFFERENCE);

        canvas.drawPath(path1, mPaint);
    }

    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    private void opTest1(Canvas canvas){

        mPaint.setStyle(Paint.Style.FILL);

        int x=80;
        int r=100;

        canvas.translate(250,0);

        Path path1 = new Path();
        Path path2 = new Path();
        Path pathOpResult = new Path();

        path1.addCircle(-x,0,r, Path.Direction.CW);
        path2.addCircle(x,0,r, Path.Direction.CW);

        pathOpResult.op(path1,path2, Path.Op.DIFFERENCE);
        canvas.translate(0, 200);
        canvas.drawText("DIFFERENCE", 240,0,mPaint);
        canvas.drawPath(pathOpResult,mPaint);

        pathOpResult.op(path1,path2, Path.Op.REVERSE_DIFFERENCE);
        canvas.translate(0, 300);
        canvas.drawText("REVERSE_DIFFERENCE", 240,0,mPaint);
        canvas.drawPath(pathOpResult,mPaint);

        pathOpResult.op(path1,path2, Path.Op.INTERSECT);
        canvas.translate(0, 300);
        canvas.drawText("INTERSECT", 240,0,mPaint);
        canvas.drawPath(pathOpResult,mPaint);

        pathOpResult.op(path1,path2, Path.Op.UNION);
        canvas.translate(0, 300);
        canvas.drawText("UNION", 240,0,mPaint);
        canvas.drawPath(pathOpResult,mPaint);

        pathOpResult.op(path1,path2, Path.Op.XOR);
        canvas.translate(0, 300);
        canvas.drawText("XOR", 240,0,mPaint);
        canvas.drawPath(pathOpResult,mPaint);
    }

    //计算边界
    //这个方法主要作用是计算Path所占用的空间以及所在位置
    private void computeBounds(Canvas canvas){
        // 移动canvas,mViewWidth与mViewHeight在 onSizeChanged 方法中获得
        canvas.translate(mWidth/2,mHeight/2);

        RectF rect1 = new RectF();              // 存放测量结果的矩形

        Path path = new Path();                 // 创建Path并添加一些内容
        path.lineTo(100,-50);
        path.lineTo(100,50);
        path.close();
        path.addCircle(-100,0,100, Path.Direction.CW);

        path.computeBounds(rect1,true);         // 测量Path

        canvas.drawPath(path,mPaint);    // 绘制Path

        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setColor(Color.RED);
        canvas.drawRect(rect1,mPaint);   // 绘制边界
    }
}
